<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
<script>


/***
 * 目标效果：sortCurry(3)(1)(7, 6)()
 * 分析思路：为什么要实现一个currify方法，然后currify(逻辑函数A)获取目标函数，而不是直接实现目标函数
 * 因为在示例效果中，能分析出来，目标函数要做两件事：1.收集参数 2.触发逻辑函数A的调用，所以说借助一个currify的工厂函数来包装一个原始函数，在这个工厂函数内部就可以做这两件事了
 */

// 所谓函数柯里化，也称作部分求值，其含义是给函数分步传递参数
// 每次参数传递返回一个更具体的函数，最后触发函数的调用
const sort = (...args) => {
    return args.sort((a, b) => a - b);
}

// 1.空参数触发调用
const currify = function (func) {
    // 建立一个数组用来存储已经传递的参数
    const args = [];
    // 柯里化处理后返回的函数
    return function curryFunc(...rest) {
        // 如果柯里化函数的触发方式为：不传参即调用
        if(rest.length === 0) {
            return func(...args); // 参数数量为0，直接调用func函数，并传入所有收集的参数即可
        } else {
            args.push(...rest); // 否则收集参数，并返回函数本身即可
            return curryFunc;
        }
    }
};
console.log(sortCurry(3)(1)(7, 6)());

// trigger函数触发调用
const currify2 = function (func) {
    // 建立一个数组用来存储已经传递的参数
    const args = [];
    // 柯里化处理后返回的函数
    function curryFunc(...rest) {
        args.push(...rest); // 否则收集参数，并返回函数本身即可
        return curryFunc;
    }
    curryFunc.trigger = () => {
        return func(...args);
    }
    return curryFunc;
};
console.log(sortCurry(3)(1)(7, 6).trigger());

// 通过console.log()直接获取函数触发结果——修改函数的toString方法
const currify3 = function (func) {
    // 建立一个数组用来存储已经传递的参数
    const args = [];
    // 柯里化处理后返回的函数
    function curryFunc(...rest) {
        args.push(...rest); // 否则收集参数，并返回函数本身即可
        return curryFunc;
    }
    curryFunc.toString = function() {
        return func(...args);
    }
    return curryFunc;
};
const sortCurry = currify(sort); // 对sort排序函数进行柯里化
console.log(sortCurry(3)(1)(7, 6));
</script>

</body>
</html>